from sklearn.feature_extraction.text import CountVectorizer
from sklearn.cluster import KMeans
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
import pandas as pd
import jieba

##############################################################################
# 显示学号36前5个和后5个新闻  -------20191106036 夏灿学号
pd.set_option('display.max_columns', None)  # 显示完整的列
pd.set_option('display.max_rows', None)  # 显示完整的行
# 读取数据
data = pd.read_excel('xw.xlsx')
data.head()
print(data[31:42])
##############################################################################
# 显示（学号最后一位）第5条新闻的标题进行分词
# 中文分词将数据的标题栏利用 jie ba 库进行分词，为后面搭建词频矩阵使用
# words = []
# for i, row in data[4:5].iterrows():
#     # print(i)
#     # print(row)
#     word = jieba.cut(row['标题'])
#     result = ' '.join(word)
#     words.append(result)
# print(words)
##############################################################################

# 对所有新闻的标题进行分词  显示前（学号最后一位）6 条   -------20191106036 夏灿学号
# 中文分词将数据的标题栏利用 jie ba 库进行分词，为后面搭建词频矩阵使用
words = []
for i, row in data.iterrows():
    word = jieba.cut(row['标题'])
    result = ' '.join(word)
    words.append(result)
print(words[0:6])

##############################################################################
# 遍历数据的每一行
# words = []
# for i, row in data.iterrows():
#     print(i)
#     print(row)
##############################################################################

# 文本向量化：建立词频矩阵;查看文本向量转变后的词袋
# Python在处理数据需要数值型数据，需要将上文的文本数据转化为词频矩阵，可以利用CountVectorizer函数
# 他的原理是将words中的每个词去重以及出去无意义的词，进行编号，然后对应每个原文本计数该次出现的次数
# 从文件导入停用词表
stoplist = "stoplist.txt"
with open(stoplist, 'rb') as fp:
    stopword = fp.read().decode('utf-8')  # 提用词提取
# 将停用词表转换为list
stpwrdlst = stopword.splitlines()

vect = CountVectorizer(stop_words=stpwrdlst)
x = vect.fit_transform(words)
x = x.toarray()
print(x)
# print(x.shape)
print('分词 :{} '.format(vect.vocabulary_))
# print(len(vect.vocabulary_))
##############################################################################

# 构造特征矩阵
# []词频矩阵处理好，需要构造特征向量为下面模型使用
words_name = vect.get_feature_names()
df = pd.DataFrame(x, columns=words_name)
# print(df)
# print(df.shape)
##############################################################################

# 模型搭建
# 通过KMeans算法进行聚类分群
kms = KMeans(n_clusters=20, random_state=0)
label_kms = kms.fit_predict(df)
print(label_kms)

##############################################################################
# 显示标签为（学号最后一位）第6类的数据来查看该分类中对应的新闻标题内容   -------20191106036 夏灿学号
words_array = np.array(words)
print(label_kms == 6)
able = words_array[label_kms == 6]
print(able)
##############################################################################

# 验证学号最后一位及之后三位的数据的欧式距离     -------20191106036 夏灿学号
dist = np.linalg.norm(df.iloc[6] - df.iloc[7])
dist1 = np.linalg.norm(df.iloc[6] - df.iloc[8])
dist2 = np.linalg.norm(df.iloc[6] - df.iloc[9])
print('第六到第七的欧式距离是：', dist)
print('第六到第八的欧式距离是：', dist1)
print('第六到第九的欧式距离是：', dist2)
##############################################################################

# 利用余弦相似度进行模型优化

# 余弦相似性通过测量两个向量的夹角的余弦值来度量它们之间的相似性。0度角的余弦值是1.
# 而其他任何角度的余弦值都不大于1；并且其最小值是-1。从而两个向量之间的角度的余弦值确定两个向量是否大致指向相同的方向。
# 两个向量有相同的指向时，余弦相似度的值为1；两个向量夹角为90°时，余弦相似度的值为0；
# 两个向量指向完全相反的方向时，余弦相似度的值为-1。这结果是与向量的长度无关的，仅仅与向量的指向方向相关。
# 余弦相似度通常用于正空间，因此给出的值为-1到1之间。
# 当文本出现重复值时，可以将原词频矩阵的数据进行余弦相似度处理，处理后的特征矩阵再带入模型。

df_cs = cosine_similarity(df)
print(df_cs[:3])
# print(df)
kms_cs = KMeans(n_clusters=9, random_state=0)
label_kms_cs = kms_cs.fit_predict(df_cs)
print(label_kms_cs)
###############################################################################
